import os
import libvirt
import sys, libxml2, time
from xml.dom import minidom
import ivic_config

#vmc_conf_path = "/etc/ivic/vmc.yaml"

#######################################################################
# collecting vmc information
def exe_command(command):
  pipe=os.popen(command,"r")
  result=pipe.readlines()
  pipe.close()
  return result

def get_default_interface():
  try:
    routes=exe_command("/sbin/route -n | sed '1,2d' | grep 'UG'")
    return routes[0].split()[7]
  except:
    print "Error in get_default_interface"
  return "eth0"

def get_ip(ifname = "eth0"):
  try:
    ip_line=exe_command("/sbin/ifconfig " + ifname + " | grep 'inet addr:'")
    return ip_line[0].split(":")[1].split()[0]
  except:
    print "Error in get_ip()"
    return "127.0.0.1"

def get_network_info():
  #net_info=[net_ifname,net_tx,net_rx]
  network_info = []
  net_ifname = ""
  net_tx = ""
  net_rx = ""
  try:
    eth_list = exe_command("/sbin/ifconfig | grep ^eth")
    for eth in eth_list:
      cur_eth_name = eth.split()[0]
      net_ifname += cur_eth_name+" "
      command="/sbin/ifconfig " + cur_eth_name + "| grep 'TX bytes:'"
      tx_line=exe_command(command)[0]
      net_tx += tx_line.split(":")[2].split()[0]+" "
      net_rx += tx_line.split(":")[1].split()[0]+" "
    network_info.append(net_ifname)
    network_info.append(net_tx)
    network_info.append(net_rx)
    return network_info
  except:
    print "Error in get_network_info()"
    return ["NA","NA","NA"]

def get_cpu_info():
  cpu_type=''
  cpu_num=0
  cpu_usage=''
  cpu_info=[]
  try:
    cputype_line=exe_command("cat /proc/cpuinfo | grep -m 1 'model name'")
    cpu_type=cputype_line[0].split(":")[1][1:]
    cpunum_lines=exe_command("cat /proc/cpuinfo | grep 'processor'")
    cpu_num=int(cpunum_lines[len(cpunum_lines)-1].split()[2])+1
    cputime_line=exe_command("head -n 1 /proc/stat")[0]
    t1=int(cputime_line.split()[1])
    t2=int(cputime_line.split()[2])
    t3=int(cputime_line.split()[3])
    t4=int(cputime_line.split()[4])
    time.sleep(1)
    cputime_line=exe_command("head -n 1 /proc/stat")[0]
    t1=int(cputime_line.split()[1])-t1
    t2=int(cputime_line.split()[2])-t2
    t3=int(cputime_line.split()[3])-t3
    t4=int(cputime_line.split()[4])-t4
    cpu_usage=float(t1+t2+t3)/(t1+t2+t3+t4)
    cpu_info.append(cpu_type)
    cpu_info.append(str(cpu_num))
    cpu_info.append(str(cpu_usage))
    return cpu_info
  except:
    print "Error in get_cpu_info()"
    return ["NA","NA","NA"]

def get_mem_info():
  mem_info=[]
  try:
    meminfo_lines=exe_command("cat /proc/meminfo")
    mem_info.append(str(int(meminfo_lines[0].split()[1])))
    mem_info.append(str(int(meminfo_lines[1].split()[1])))
    return mem_info
  except:
    print "Error in get_mem_info()"
    return ["NA","NA"]

def get_disk_info():
  disk_device=''
  disk_total=''
  disk_free=''
  disk_info=[]
  try:
    disklines=exe_command("df | grep '^\/dev\/'")
    for line in disklines:  
      disk_device+=line.split()[0]+" "
      disk_total+=line.split()[1]+" "
      disk_free+=line.split()[3]+" "
    disk_info.append(disk_device)
    disk_info.append(disk_total)
    disk_info.append(disk_free)
    return disk_info
  except:
    print "Error in get_disk_info()"
    return ["NA","NA","NA"]

##############################################################################################
# collecting dom information

def get_domlist_info():
  dom_uuids = get_all_dom_uuids()
  dom_statuses = []
  for dom_uuid in dom_uuids:
    dom_statuses.append(get_dom_status(dom_uuid))
  return dom_uuids, dom_statuses

def get_dom_status(dom_uuid):
  try:
    status = os.popen("virsh domstate " + dom_uuid, "r").readline().strip()
    if status == "":
      status = "stopped"
    return status
  except:
    return "stopped"

def get_all_dom_uuids():
  #vmcconf=minidom.parse("/etc/vmc.conf").documentElement
  #imageRoot=vmcconf.getElementsByTagName("imageRoot")[0].firstChild.data.strip()
  #imageRoot='../ivic_refine_20090326/data/var/lib/ivic/vmc/images'
  #return os.listdir(os.getcwd()) #(imageRoot)
  #image_root = Config.load(vmc_conf_path)['image_root']
  vmxml_root = ivic_config.get_dir("vmxml_root")
  if os.path.exists(vmxml_root):
    names = os.listdir(vmxml_root)
  else:
    return []
  names = filter(lambda x:x.endswith(".xml"), names)
  for i in xrange(len(names)):
    names[i] = names[i][0:-4]
  return names

def get_dom_uuids():
  """
  return list of all running dom ids, if null, return []
  """
  dom_uuids = []
  dom_names = []

  virsh_lists = os.popen("virsh list | sed '1,2d' | grep -v '^$'", "r").readlines()
  for virsh_list_entry in virsh_lists:
    dom_uuid = virsh_list_entry.split()[0]
    dom_name = os.popen("virsh domname " + dom_uuid, "r").readline()
    if dom_name != "Domain-0\n":
      dom_uuids.append(virsh_list_entry.split()[0])
      dom_names.append(dom_name.strip())

  return (dom_uuids, dom_names)

def get_vnc_port(dom_uuid):
  try:
    return  os.popen("virsh vncdisplay " + dom_uuid, "r").readline().split(":")[1].strip()
  except:
    return "NA"

def get_dom_info(dom_uuid):
  """
  return [uuid, state, cputime, memtotal, memused, disk_read, disk_write, vif_rx, vif_tx, vnc_port]
  """
  returnvalue = ["", "", "", "", "", "", "", "", "", ""]

  dom_infos = os.popen("virsh dominfo " + dom_uuid, "r").readlines()
  returnvalue[0] = dom_infos[2].split()[1] + " "
  returnvalue[1] = "running "
  returnvalue[2] = dom_infos[6].split()[2] + " "
  returnvalue[3] = dom_infos[7].split()[2] + " "
  returnvalue[4] = dom_infos[8].split()[2] + " " # should be free mem

  returnvalue[5:9] = get_dom_disk_and_vif_info(dom_uuid)
  returnvalue[9] = get_vnc_port(dom_uuid)

  return returnvalue

def get_dom_disk_and_vif_info(dom_uuid):
  """
  return [sda1:sda2:...:disk_read, disk_write, vif1:vif2:vif_tx, vif_rx]
  """
  returnvalue = ["", "", "", ""]

  if dom_uuid != "0":
    dumpxml = os.popen("virsh dumpxml " + dom_uuid, "r").read()
    disk_names, vif_names = analyse_dumpxml(dumpxml)
    a, b = get_dom_disk_info(disk_names, dom_uuid)
    returnvalue[0] = a
    returnvalue[1] = b
    c, d = get_dom_vif_info(vif_names, dom_uuid)
    returnvalue[2] = c
    returnvalue[3] = d

  return returnvalue

def get_dom_disk_info(disk_names, dom_uuid):
  returnvalue=("NA", "NA")
  disk_read = 0
  disk_write = 0

  if disk_names != []:
    for disk_name in disk_names:
      diskinfo = os.popen("virsh domblkstat " + dom_uuid + " " + disk_name, "r").readlines()
      disk_read += int(diskinfo[0].split()[2])
      disk_write += int(diskinfo[1].split()[2])
    returnvalue = str(disk_read), str(disk_write)

  return returnvalue

def get_dom_vif_info(vif_names, dom_uuid):
  returnvalue=("NA", "NA")
  vif_rx = 0
  vif_tx = 0

  if vif_names != []:
    for vif_name in vif_names:
      vifinfo = os.popen("virsh domifstat " + dom_uuid + " " + vif_name, "r").readlines()
      vif_rx += int(vifinfo[0].split()[2])
      vif_tx += int(vifinfo[4].split()[2])
  returnvalue = str(vif_rx), str(vif_tx)

  return returnvalue

def analyse_dumpxml(dumpxml):
  returnvalue = [[],[]]

  ps = minidom.parseString(dumpxml)

  disks = ps.getElementsByTagName("disk")
  for disk in disks:
    returnvalue[0].append(disk.getElementsByTagName("target")[0].attributes["dev"].value.encode())

  vifs = ps.getElementsByTagName("interface")
  for vif in vifs:
    returnvalue[1].append(vif.getElementsByTagName("target")[0].attributes["dev"].value.encode())

  return returnvalue

##############################################################################################
#     about the network

def get_networklist_info():
  network_uuids = get_all_network_uuids()
  network_statuses = []
  network_vpnservers = []
  for network_uuid in network_uuids:
    network_statuses.append(get_network_status(network_uuid))
    network_vpnservers.append(get_network_vpnserver(network_uuid))
  return network_uuids, network_statuses, network_vpnservers

def get_all_network_uuids():
  #vmcconf = minidom.parse("/etc/vmc.conf").documentElement
  #networkRoot = vmcconf.getElementsByTagName("networkRoot")[0].firstChild.data.strip()
  #networkRoot = '../ivic_refine_20090326/data/var/lib/ivic/vmc/network'
  #names = os.listdir(os.getcwd()) #(networkRoot)
  #network_root = Config.load(vmc_conf_path)['network_root']
  network_root = ivic_config.get_dir("network_root")
  if os.path.exists(network_root):
    names = os.listdir(network_root)
  else:
    return []
  names = filter(lambda x:x.endswith(".xml"), names)
  for i in xrange(len(names)):
    names[i] = names[i][0:-4]
  return names

def get_network_status(network_uuid):
  try:
    if os.popen("virsh net-list | grep " + network_uuid, "r").readline() != '':
      return "active"
  except:
    return "inactive"
  return "inactive"
def get_network_vpnserver(network_uuid):
  try:
    return os.popen("cat /etc/openvpn/" + network_uuid + "/client.conf", "r").readlines()[3].split()[1]
  except:
    return "NA"
